using System;
using System.Collections.Generic;
using UnityEngine;

public class PlayerQuestManager : MonoBehaviour, ISaveable
{
    public event Action<QuestData> OnQuestFinish; //当任务完成时
    public event Func<QuestDataSO[]> OnFindHasQuest; //查找是否还有任务
    public event Action OnAddQuestAmount; //当任务计数增加时
    public QuestDataBaseSO questDataBaseSO;
    private Inventory_Player inventory;
    [SerializeField] private List<QuestData> questList = new();
    [SerializeField] private int maxAcceptQuestCount = 2;

    private void Awake()
    {
        inventory = GetComponent<Inventory_Player>();
    }

    //尝试增加任务计数
    public void TryAddQuestAmount(string questTargetId, int amount = 1)
    {
        var targetQuest = questList.Find(target => target.questDataSO.questTargetId == questTargetId);

        if (targetQuest == null)
            return;

        targetQuest.AddRequireAmount(amount);
        OnAddQuestAmount?.Invoke();
    }

    public void TryGiveRewardFrom(RewardType npcType)
    {
        List<QuestData> getRewardQuests = new();
        foreach (var quest in questList)
        {
            if (quest.questDataSO.questType == QuestType.Delivery)
            {

                Inventory_Item[] itemDatas = quest.questDataSO.itemToDelivery;

                if (inventory.HasEnoughDeliveryItem(itemDatas) == false)
                    continue;

                for (int i = 0; i < itemDatas.Length; i++)
                    inventory.RemoveItemAmount(itemDatas[i]);
            }
            if (quest.CanGetReward() && quest.questDataSO.rewardType == npcType)
                getRewardQuests.Add(quest);
        }
        if (getRewardQuests.Count == 0)
            return;

        foreach (var quest in getRewardQuests)
            FinishQuest(quest);

    }

    public void FinishQuest(QuestData getRewardQuests)
    {
        questList.Remove(getRewardQuests);

        OnQuestFinish?.Invoke(getRewardQuests);
    }

    public void AcceptQuest(QuestDataSO questToAccept)
    {
        questList.Add(new(questToAccept));
    }

    public bool CanAcceptQuest() => questList.Count < maxAcceptQuestCount;

    //判断是否已经接受任务了（任务是否在列表中）
    public bool IsAcceptedQuest(QuestDataSO questToFind)
    {
        if (questToFind == null)
            return false;

        return questList.Find(target => target.questDataSO == questToFind) != null;
    }

    public void CancelQuest(QuestDataSO questToCancel)
    {
        var questToRemove = questList.Find(target => target.questDataSO == questToCancel);
        if (questToRemove == null)
            return;
        questList.Remove(questToRemove);
    }

    public List<QuestData> GetQuestList() => questList;

    public void SaveData(ref GameData gameData)
    {
        gameData.quests.Clear();

        foreach (var questToSave in questList)
            gameData.quests.Add(questToSave.questDataSO.questSaveId, questToSave.requireAmount);
    }

    public void LoadData(GameData gameData)
    {
        foreach (var questToLoad in gameData.quests)
        {
            string questId = questToLoad.Key;
            int questRequireAmount = questToLoad.Value;
            QuestDataSO questDataSO = questDataBaseSO.GetQuestById(questId);

            if (questDataSO == null)
                continue;

            QuestData questData = new(questDataSO)
            {
                requireAmount = questRequireAmount,
            };

            questList.Add(questData);
        }
    }

    //判断是否有完成任务
    public bool IsFinishQuest(RewardType npcType) => questList.Find(match => match.rewardType == npcType && match.isFinishQuest) != null;

    //判断是否还有任务
    public bool HasQuestInRewardType(RewardType npcType)
    {
        List<QuestDataSO> allQuestDataSO = new();
        foreach (Delegate handler in OnFindHasQuest.GetInvocationList())
        {
            Func<QuestDataSO[]> func = handler as Func<QuestDataSO[]>;
            QuestDataSO[] result = func.Invoke();
            allQuestDataSO.AddRange(result);
        }
        return allQuestDataSO.Find(target => target.rewardType == npcType);
    }
}